import { remove } from "../module/jszip/jszip";
import { AStar } from "./findpath/AStar";
import { GridMap } from "./findpath/Grid";
import { AstarNode } from "./findpath/Node";
import Unit from "./Unit";
import { UnitStateEnum } from "./UnitStateMachine";

export default class MoveComponent {
    public unit: Unit;
    public speed: number;

    public aimNode: AstarNode;
    public nowPos: cc.Vec2;
    private path: AstarNode[];
    private duration: number;
    private nowTime: number;
    private distance: number;
    private callback: Function;
    private endPos: cc.Vec2;
    constructor(unit: Unit) {
        this.unit = unit;
        this.path = [];
        unit.moveComponent = this;
        this.speed = unit.getProperty('moving_speed');
    }

    public canelMove() {
        cc.Tween.stopAllByTarget(this.unit);
        //this.aimNode = null;
    }
    public move(x: number, y: number, callback?) {
        this.canelMove();
        this.nowTime = 0;
        this.nowPos = this.unit.gridPos;
        this.path = AStar.instance.findPath(this.nowPos, cc.v2(x, y));
        if (callback) {
            this.callback = callback;
        }
        if (this.path.length == 0) {
            setTimeout(() => {
                this.unit.changeState(UnitStateEnum.FindAim);
            }, Math.random()*100);
            return;
        }
        this.endPos = this.path[this.path.length - 1].position;
        this.path.shift();
        this.aimNode = this.path.shift();
        if (this.aimNode) {
            this.unit.anim.play('M');
            GridMap.instance.getNode(this.nowPos.x, this.nowPos.y).hasUnit = false;
            this.aimNode.hasUnit = true;
            this.unit.direction = this.aimNode.position.sub(this.nowPos);
            this.unit.gridPos = this.aimNode.position;
            this.distance = this.unit.direction.len();
            this.duration = this.distance / this.speed;
            cc.tween(this.unit).to(this.duration, { pos: this.aimNode.position }).call(this.next.bind(this)).start();
        }

    }

    private next() {
        this.nowTime = 0;

        this.nowPos = this.aimNode.position;
        if (!this.unit.fsm.aim||this.unit.fsm.aim.isDeath()) {
            this.unit.changeState(UnitStateEnum.FindAim);
            return;
        }
        let self = this.unit;
        let attackDistance = self.getProperty('atk_range');
        let direction = self.gridPos.sub(this.unit.fsm.aim.gridPos);
        if (direction.len() <= attackDistance) {
            self.changeState(UnitStateEnum.Attack);
            return;
        }

        let distance = this.endPos.sub(this.unit.fsm.aim.gridPos).len();

        if (distance > attackDistance) {

            this.unit.changeState(UnitStateEnum.FindAim);
            return;
        }

        this.aimNode = this.path.shift();

        if (!this.aimNode) {
            this.unit.changeState(UnitStateEnum.FindAim);
           
            return;
        }
        if (this.aimNode.hasUnit) {
            this.unit.changeState(UnitStateEnum.FindAim);
            return;
        } else {
            GridMap.instance.getNode(this.nowPos.x, this.nowPos.y).hasUnit = false;
            this.aimNode.hasUnit = true;
            this.unit.direction = this.aimNode.position.sub(this.nowPos);
            this.unit.gridPos = this.aimNode.position;
            this.distance = this.unit.direction.len();
            this.duration = this.distance / this.speed;
            cc.tween(this.unit).to(this.duration, { pos: this.aimNode.position }).call(this.next.bind(this)).start();
        }
    }
}